Kubernetes是一个容器编排系统,可以管理集群中的容器化应用程序。维持群集中所有容器之间的网络联通需要一些高级网络特性。在本文中,我们将简要介绍一些检查集群网络的工具和技巧。
如果您要调试网络连接、网络吞吐量或者是探索Kubernetes以了解其运行方式,则这些工具可能很有用。
如果您想全面了解Kubernetes,我们的指南《 Kubernetes简介》将介绍基础知识。有关Kubernetes的网络概述,请阅读深入了解Kubernetes网络。
Finding a Pod’s Cluster IP
要查找Kubernetes Pod的 cluster IP,可以 kubectl get pod -o wide
。此选项将列出更多信息,包括Pod所在的节点以及Pod的 IP。
1 | kubectl get pod -o wide |
该IP列是pod的 集群内部 IP。
如果没有找到所需的pod,请确保您在正确的namespace中。您可以通过添加flag列出所有namespaces中的所有pod --all-namespaces
。
Finding a Service’s IP
我们也可以使用kubectl
找到Service IP 。在这里,我们列出所有namespaces中的所有service:
1 | kubectl get service --all-namespaces |
Service IP可以在CLUSTER-IP列中找到。
Finding and Entering Pod Network Namespaces
每个Kubernetes Pod被分配了自己的network namespace。 Network namespaces(netns)是Linux网络原语,可在网络设备之间提供隔离。
从Pod的netns里执行命令来检查DNS解析或常规的网络连接是很有用的。为此,我们首先需要查找pod中一个container的进程ID。对于Docker,我们可以下面方法来查找。
首先,列出在节点上运行的容器:
1 | docker ps |
在输出中找到CONTAINER ID或容器的name。在上面,我们列出了两个容器:
- 第一个容器是在
hello-world
pod 中运行了一个hello-world
应用 - 第二个容器是在
hello-world
pod中运行的pause。该容器是提供共享Pod的network namespace
要获取容器的进程ID,请记下容器ID或名称,并在以下docker
命令中获取:
1 | docker inspect --format '{{ .State.Pid }}' container-id-or-name |
将输出一个进程ID(或PID)。现在,我们可以使用该nsenter
命令在该进程的network namespace中运行命令:
1 | nsenter -t your-container-pid -n ip addr |
确保使用自己的PID,并替换ip addr
为要在Pod的network namespace中运行的命令。
注意: 使用nsenter
去访问Pod的namespace,相较于docker exec
等方式,它可以使用节点上所有可用的命令。
Finding a Pod’s Virtual Ethernet Interface
每个Pod的network namespace都通过virtual ethernet pipe与节点的root netns通信。在节点一侧,此设备通常以veth
开头,并以一个唯一标识符结尾(例如veth77f2275
或veth01
)。在pod中,此设备显示为eth0
。
了解哪个veth
设备与特定的Pod关联是很有用的。为此,我们在节点上列出所有网络设备,然后在Pod的network namespace中列出设备。然后,我们可以关联相关的设备编号。
首先,通过nsenter
在Pod的network namespace中执行ip addr
:
1 | nsenter -t your-container-pid -n ip addr |
该命令将输出Pod网卡设备列表。注意示例中eth0@
后面的数字if11
。这意味着此pod的eth0
链接到节点的第11个接口。现在在节点的默认namespace 中执行ip addr
:
1 | ip addr |
veth4f7342d
是在此示例输出中的第11个接口。这正是我们查找的Pod的 virtual ethernet pipe。
检查Conntrack连接跟踪
在1.11版之前,Kubernetes使用iptables NAT和conntrack内核模块来跟踪连接。要列出当前正在跟踪的所有连接,请使用以下conntrack
命令:
1 | conntrack -L |
要持续监视新连接,请使用-E
标志:
1 | conntrack -E |
要列出由conntrack跟踪的到特定目标地址的连接,请使用-d
标志:
1 | conntrack -L -d 10.32.0.1 |
如果您的节点在建立与服务的可靠连接时遇到问题,有可能是nf_conntrack table已满,新建立连接会被删除。如果是这种情况,您可能会在系统日志中看到类似以下的消息:
/var/log/syslog
1 | Jul 12 15:32:11 worker-528 kernel: nf_conntrack: table full, dropping packet. |
对于要跟踪的最大连接数,可以使用sysctl设置。您可以使用以下命令列出当前值:
1 | sysctl net.netfilter.nf_conntrack_max |
要设置新值,请使用-w
标志:
1 | sysctl -w net.netfilter.nf_conntrack_max=198000 |
要使此设置永久生效,请将其添加到sysctl.conf
文件中:
/etc/sysctl.conf
1 | . . . |
检查Iptables规则
在1.11版之前,Kubernetes使用iptables NAT来实现虚拟IP转换和服务IP的负载均衡。
要在节点上转储所有iptables规则,请使用以下iptables-save
命令:
1 | iptables-save |
要仅列出Kubernetes服务NAT规则,请使用iptables
命令和-L
标志指定正确的链:
1 | iptables -t nat -L KUBE-SERVICES |
Querying Cluster DNS
调试群集DNS解析的一种方法是在容器中安装调式工具,然后在kubectl exec
进去执行nslookup
。Kubernetes官方文档对此进行了描述。
查询群集DNS的另一种方法是在节点上使用dig
和nsenter
。如果dig
未安装,则可以安装:
1 | apt install dnsutils |
首先,找到kube-dns服务的cluster IP :
1 | kubectl get service -n kube-system kube-dns |
接下来,我们使用nsenter
,然后在容器名称空间中运行dig
:
1 | nsenter -t 14346 -n dig kubernetes.default.svc.cluster.local @10.32.0.10 |
此dig
命令查找服务的完整域名service-name.namespace.svc.cluster.local ,并指定群集DNS服务service IP(`@10.32.0.10`)
Looking at IPVS Details
从Kubernetes 1.11开始,kube-proxy
可以将IPVS配置为处理virtual Service IP到Pod IP的转换。您可以使用ipvsadm
列出IP的转换表:
1 | ipvsadm -Ln |
要显示单个服务IP,请使用-t
选项并指定所需的IP:
1 | ipvsadm -Ln -t 100.64.0.10:53 |
原文:
https://www.digitalocean.com/community/tutorials/how-to-inspect-kubernetes-networking#